<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    async function fetchBlob(link) {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log('执行完成:' + link);
          resolve();
        }, 2000)
      });
    }

    function concurrentFetch(urls, request, maxNum = 4) {
      return new Promise((resolve) => {
        if (urls.length === 0) {
          resolve([]);
          return
        }
        const rc = [];
        let currentIndex = 0;
        let completeCount = 0;
        const run = async () => {
          const i = currentIndex;
          const url = urls[i];
          try {
            const data = await request(url);
            rc[i] = { data, success: true, };
          } catch (error) {
            rc[i] = { data: error, success: false, };
          } finally {
            completeCount += 1;
            next();
          }
        };
        const next = () => {
          if (completeCount >= urls.length) {
            resolve(rc);
            return;
          }
          if (currentIndex >= urls.length - 1) {
            return;
          }
          currentIndex++;
          run(currentIndex);
        }
        const steps = Math.min(urls.length, maxNum);
        for (let index = 0; index < steps; index++) {
          currentIndex = index;
          run(index);
        }
      });
    }

    (async () => {
      const st = Date.now();
      console.log('time start', st);
      const array = new Array(10).fill(0).map((_, i) => i);

      // for (let index = 0; index < array.length; index++) {
      //   const element = array[index];
      //   await fetchBlob(element);
      // }

      await concurrentFetch(array, fetchBlob);
      console.log('time end', (Date.now() - st) / 1000);
    })();

  </script>
</body>

</html>